package tests;

import jeconbond.economic.EconomicEngine;
import jeconbond.economic.IEconomicEngine;
import jeconbond.economic.agent.IEconomicAgent;
import jeconbond.economic.agent.service.IPostActServiceAgent;
import jeconbond.economic.agent.service.IPreActServiceAgent;
import jeconbond.economic.resources.ResourceType;
import jeconbond.economic.resources.IResourceType;
import jeconbond.economic.systems.IResourceRedestributionSystem;
import jeconbond.economic.systems.market.DefaultMarketResourceRedestributionSystem;
import junit.framework.Assert;
import junit.framework.TestCase;

public class TestWorkFlow extends TestCase {
	public void testEngine() {
		IEconomicEngine engine = new EconomicEngine();
		final StringBuffer sb = new StringBuffer(); 
		engine.addAgents(
				new IPostActServiceAgent() {
					public void processPreProduceStage() {
						sb.append("Serv:post,Stage:pre;");
					}
					public void processProduceStage() {
						sb.append("Serv:post,Stage:main;");
					}
					public void processPostProduceStage() {
						sb.append("Serv:post,Stage:post;");
					}
				},
				new IEconomicAgent() {
					public void processPreProduceStage() {
						sb.append("Agent,Stage:pre;");
					}
					public void processProduceStage() {
						sb.append("Agent,Stage:main;");
					}
					public void processPostProduceStage() {
						sb.append("Agent,Stage:post;");
					}
				},
				new IPreActServiceAgent() {
					public void processPreProduceStage() {
						sb.append("Serv:pre,Stage:pre;");
					}
					public void processProduceStage() {
						sb.append("Serv:pre,Stage:main;");
					}
					public void processPostProduceStage() {
						sb.append("Serv:pre,Stage:post;");
					}
				}
		);
		IResourceRedestributionSystem mrrs = 
			new DefaultMarketResourceRedestributionSystem();
		engine.processSteps(3, mrrs);
		String log = sb.toString();
		Assert.assertEquals(
				"Serv:pre,Stage:pre;Agent,Stage:pre;Serv:post,Stage:pre;" +
				"Serv:pre,Stage:main;Agent,Stage:main;Serv:post,Stage:main;" +
				"Serv:pre,Stage:post;Agent,Stage:post;Serv:post,Stage:post;" +
				
				"Serv:pre,Stage:pre;Agent,Stage:pre;Serv:post,Stage:pre;" +
				"Serv:pre,Stage:main;Agent,Stage:main;Serv:post,Stage:main;" +
				"Serv:pre,Stage:post;Agent,Stage:post;Serv:post,Stage:post;" +
				
				"Serv:pre,Stage:pre;Agent,Stage:pre;Serv:post,Stage:pre;" +
				"Serv:pre,Stage:main;Agent,Stage:main;Serv:post,Stage:main;" +
				"Serv:pre,Stage:post;Agent,Stage:post;Serv:post,Stage:post;", 
				log
		);
	}
	
	public void testNaturalWorkFlow() {
		IResourceType ground = new ResourceType("Ground");
		IResourceType wood = new ResourceType("Wood");
		IResourceType fire = new ResourceType("Fire");
		
		tests.fakes.NaturalResourceRedestributionSystem nrrs =
			new tests.fakes.NaturalResourceRedestributionSystem();
		
		IEconomicAgent reuseGroundAgent = 
			new tests.fakes.ReuseGroundAgent(nrrs, ground);
		IEconomicAgent ground2wood = 
			tests.fakes.ResourceConverter.GeterateConverter(nrrs, ground, wood);
		IEconomicAgent wood2fire = 
			tests.fakes.ResourceConverter.GeterateConverter(nrrs, wood, fire);

		IEconomicEngine engine = new EconomicEngine();
		engine.addAgents(
				reuseGroundAgent, 
				ground2wood, 
				wood2fire
		);
		
		Assert.assertEquals(0.0, nrrs.howMuchWasStored(fire));
		engine.processSteps(1, nrrs);
		Assert.assertEquals(0.0, nrrs.howMuchWasStored(fire));
		engine.processSteps(1, nrrs);
		Assert.assertEquals(1.0, nrrs.howMuchWasStored(fire));
		engine.processSteps(10, nrrs);
		Assert.assertEquals(6.0, nrrs.howMuchWasStored(fire));
		Assert.assertEquals(0.0, nrrs.howMuchWasStored(wood));
		Assert.assertEquals(12, nrrs.stepsProcCounter);
	}
	
	public void testEngineEvents() {
		IEconomicEngine engine = new EconomicEngine();
		final StringBuilder sb = new StringBuilder();
		IEconomicAgent agent = new IEconomicAgent() {
			public void processPostProduceStage() {
				sb.append("processPostProduceStage()");
			}
			public void processPreProduceStage() {
				sb.append("processPreProduceStage()");
			}
			public void processProduceStage() {
				sb.append("processProduceStage()");
			}
		};
		IResourceRedestributionSystem rrs = new IResourceRedestributionSystem() {
			public void onProduceStageCompleted() {
				sb.append("onProduceStageComplited()");
			}
		};
		engine.addAgents(agent);
		engine.processSteps(1, rrs);
		Assert.assertEquals(
				"processPreProduceStage()" +
				"processProduceStage()" +
				"onProduceStageComplited()" +
				"processPostProduceStage()", 
				sb.toString()
		);
	}
}
